import axios from 'axios'
import ErrorHandle from './errorHandler'
import store from '@/store'
import publicConfig from '@/config'
const CancelToken = axios.CancelToken
class HttpRequest {
  constructor (baseUrl) {
    this.baseUrl = baseUrl
    this.pending = {}
  }

  getInsideConfig () {
    const config = {
      baseURL: this.baseUrl,
      headers: {
        'Content-Type': 'application/json;charset=utf-8'
      }
      // timeout: 10000
    }
    return config
  }

  removePending (key, isRequest = false) {
    if (this.pending[key] && isRequest) {
      this.pending[key]('已取消本次发送请求')
    }
    delete this.pending[key]
  }

  interceptors (instance) {
    // 添加请求拦截器
    instance.interceptors.request.use((config) => {
      // 在发送请求之前做些什么
      const key = `${config.url}&${config.method}`
      if (!config.multiple) {
        this.removePending(key, true)
        config.cancelToken = new CancelToken((c) => {
          this.pending[key] = c
        })
      }

      let isPublic = false
      publicConfig.publicPath.forEach(elem => {
        isPublic = isPublic || elem.test(config.url)
      })
      const token = store.state.token
      if (token && !isPublic) {
        config.headers.Authorization = `Bearer ${token}`
      }

      return config
    }, function (error) {
      ErrorHandle(error)
      // 对请求错误做些什么
      return Promise.reject(error)
    })

    // 添加响应拦截器
    instance.interceptors.response.use((res) => {
      const key = `${res.config.url}&${res.config.method}`
      this.removePending(key)
      // 对响应数据做点什么
      if (res.status === 200) {
        return Promise.resolve(res.data)
      } else {
        return Promise.reject(res)
      }
    }, function (error) {
      ErrorHandle(error)
      // 对响应错误做点什么
      return Promise.reject(error)
    })
  }

  // 创建实例
  request (options) {
    const config = this.getInsideConfig()
    const newOptions = Object.assign(config, options)
    const instance = axios.create()
    this.interceptors(instance)
    return instance(newOptions)
  }

  get (url, options = {}) {
    return this.request({
      url,
      ...options,
      method: 'get'
    })
  }

  post (url, data) {
    return this.request({
      url,
      method: 'post',
      data
    })
  }

  put (url, data) {
    return this.request({
      url,
      method: 'put',
      data
    })
  }

  delete (url, data) {
    return this.request({
      url,
      method: 'delete',
      data
    })
  }
}

export default HttpRequest
